package com.liao.ticket.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.liao.ticket.common.exception.ErrorCode;
import com.liao.ticket.dao.mapper.AirportMapper;
import com.liao.ticket.dao.pojo.Airport;
import com.liao.ticket.service.AirportService;
import com.liao.ticket.util.AdminThreadLocal;
import com.liao.ticket.util.CheckPowerUtils;
import com.liao.ticket.vo.AirportVo;
import com.liao.ticket.vo.Result;
import com.liao.ticket.vo.params.AirportParams;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;

@Service
@Transactional
public class AirportServiceImpl implements AirportService {

    @Autowired
    private AirportMapper airportMapper;

    @Override
    public AirportVo oneAirportVo(Long id) {
        return copy(airportMapper.selectById(id));
    }

    @Override
    public List<AirportVo> listAirportVoByPlace(String placeName) {
        return copy(selectAirportList(placeName,null,null));
    }

    @Override
    public List<AirportVo> listAirportVoByName(String name) {
        return copy(selectAirportList(null,name,null));
    }

    @Override
    public List<AirportVo> listAirportVoByPlaceOrName(String name) {
        LambdaQueryWrapper<Airport> wrapper = new LambdaQueryWrapper<>();
        wrapper.likeRight(Airport::getPlaceName, name).or().likeRight(Airport::getName, name);
        return copy(airportMapper.selectList(wrapper));
    }

    @Override
    public List<AirportVo> listAirportVoByPid(Integer id) {
        return copy(selectAirportList(null,null,id));
    }

    @Override
    public Result addOne(AirportParams airportParams) {
        if (AdminThreadLocal.get() == null) {
            return Result.fail(ErrorCode.USER_NO_POWER);
        }
        if (check(airportParams, false, true, true, true)) {
            return Result.fail(ErrorCode.USER_AIRPORT_ADD_PARAMS_FAIL);
        }
        Airport airport = selectAirportByName(airportParams.getName());
        if(airport != null){
            return Result.fail(ErrorCode.USER_AIRPORT_ALREADY_EXIT);
        }
        airport = new Airport();
        airport.setName(airportParams.getName());
        airport.setPlaceName(airportParams.getPlaceName());
        airport.setPid(airportParams.getPid());
        airportMapper.insert(airport);
        return Result.success(copy(airport));
    }

    @Override
    public Result updateOneById(AirportParams airportParams) {
        Long mid = CheckPowerUtils.getMid(20);
        if (!((mid = CheckPowerUtils.getMid(0)) != null || (mid = CheckPowerUtils.getMid(20)) != null)) {
            return Result.fail(ErrorCode.USER_NO_POWER);
        }
        if((StringUtils.isBlank(airportParams.getName())
                && StringUtils.isBlank(airportParams.getPlaceName())
                && airportParams.getPid() == null)
                || airportParams.getId() == null)
        {
            return Result.fail(ErrorCode.USER_AIRPORT_UPDATE_PARAMS_FAIL);
        }
        if(airportParams.getName() != null){
            if (selectAirportByName(airportParams.getName()) != null) {
                return Result.fail(ErrorCode.USER_AIRPORT_ALREADY_EXIT);
            }
        }
        if(mid == 0){
            mid = airportParams.getId();
        }
        Airport airport = new Airport(mid, airportParams.getPid(), airportParams.getPlaceName(), airportParams.getName());
        return Result.success(airportMapper.updateById(airport));
    }

    @Override
    public Result updateListPlaceNameByPid(AirportParams airportParams) {
        if (AdminThreadLocal.get() == null) {
            return Result.fail(ErrorCode.USER_NO_POWER);
        }
        if(check(airportParams,false,false,true,true)){
            return Result.fail(ErrorCode.USER_AIRPORT_UPDATE_PARAMS_FAIL);
        }
        Airport airport = new Airport();
        airport.setPlaceName(airportParams.getPlaceName());
        LambdaQueryWrapper<Airport> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Airport::getPid, airportParams.getPid());
        return Result.success(airportMapper.update(airport, wrapper));
    }

    @Override
    public Result deleteOneById(Long id) {
        if (AdminThreadLocal.get() == null) {
            return Result.fail(ErrorCode.USER_NO_POWER);
        }
        return Result.success(airportMapper.deleteById(id));
    }

    @Override
    public Result deleteListByPid(Integer id) {
        if (AdminThreadLocal.get() == null) {
            return Result.fail(ErrorCode.USER_NO_POWER);
        }
        LambdaQueryWrapper<Airport> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Airport::getPid, id);
        return Result.success(airportMapper.delete(wrapper));
    }

    private Airport selectAirportByName(String name) {
        if (StringUtils.isBlank(name)) {
            return null;
        }
        LambdaQueryWrapper<Airport> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Airport::getName, name);
        Airport airport = airportMapper.selectOne(wrapper);
        return airport;
    }

    private List<Airport> selectAirportList(String placeName, String name, Integer pid) {
        LambdaQueryWrapper<Airport> wrapper = new LambdaQueryWrapper<>();
        if (placeName != null) {
            wrapper.likeRight(Airport::getPlaceName, placeName);
        }
        if (name != null) {
            wrapper.likeRight(Airport::getName, name);
        }
        if (pid != null) {
            wrapper.eq(Airport::getPid, pid);
        }
        return airportMapper.selectList(wrapper);
    }

    private AirportVo copy(Airport airport) {
        if (airport == null){
            return new AirportVo();
        }
        AirportVo airportVo = new AirportVo();
        BeanUtils.copyProperties(airport, airportVo);
        return airportVo;
    }

    private List<AirportVo> copy(List<Airport> airportList) {
        List<AirportVo> airportVoList = new ArrayList<>();
        for (Airport airport : airportList) {
            airportVoList.add(copy(airport));
        }
        return airportVoList;
    }

    private Boolean check(AirportParams airportParams,Boolean id, Boolean name, Boolean placeName, Boolean pid) {
        Boolean ok = true;
        if (id && ok) {
            ok = airportParams.getId() != null || airportParams.getId() != 0L;
        }
        if (name && ok) {
            ok = StringUtils.isAllBlank(airportParams.getName());
        }
        if (placeName && ok) {
            ok = StringUtils.isAllBlank(airportParams.getPlaceName());
        }
        if (pid && ok) {
            ok = airportParams.getPid() != null || airportParams.getPid() != 0;
        }
        return ok;
    }

    public static void main(String[] args) {
        System.out.println();
    }
}
